package model.trivial_pursuit;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.LinkedList;

import model.DbTable;

import database.ValuedAttribute;

/**
 * Classe de communication avec la table de themes du Trivial Pursuit de la BDD
 * @author Aubry Pirian
 *
 */
public class Theme extends DbTable {
	
	private int id=-1;		// Numéro du theme
	private String name;	// Nom du theme
	HashMap<String,String> colors;
	
	/**
	 * Constructeur de nouveau Theme
	 * @throws NoSuchFieldException : paramètre non valide
	 * @throws SQLException 
	 * @throws ClassNotFoundException : impossible d'accéder au driver JDBC 
	 */
	public Theme () throws ClassNotFoundException, SQLException, NoSuchFieldException {
		super(TPParams.THEME_TABLE);
		this.initColors();
	}
	
	/**
	 * Constructeur de theme par numéro
	 * @param id : numéro du theme
	 * @throws NoSuchFieldException : paramètre non valide
	 * @throws SQLException 
	 * @throws ClassNotFoundException : impossible d'accéder au driver JDBC
	 */
	public Theme (int id) throws ClassNotFoundException, SQLException, NoSuchFieldException {
		super(TPParams.THEME_TABLE);
		this.initColors();
		this.id=id;
		this.read(id);
	}
	
	/**
	 * Constructeur de theme par nom
	 * @param name : nom du theme
	 * @throws NoSuchFieldException : paramètre non valide
	 * @throws SQLException 
	 * @throws ClassNotFoundException : impossible d'accéder au driver JDBC
	 */
	public Theme(String name) throws ClassNotFoundException, SQLException, NoSuchFieldException {
		super(TPParams.THEME_TABLE);
		this.initColors();
		this.name = name;
		try {
			this.read(name);
		} catch (SQLException e) {
			throw e;
		} catch (NoSuchFieldException e) {
			throw e;
		}
	}
	
	private void initColors () {
		colors = new HashMap<String, String>();
		int nbColors = TPParams.COLORS.length;
		for (int i=0; i<nbColors; i++) {
			this.colors.put(TPParams.COLORS[i][0],TPParams.COLORS[i][1]);
		}
	}
	
	/**
	 * Méthode récupérant les informations dans la BDD, par numéro
	 * @param id : numéro du theme
	 * @throws SQLException 
	 * @throws NoSuchFieldException : paramètre non valide
	 */
	public void read (int id) throws SQLException, NoSuchFieldException {
		ResultSet rs;
		try {
			rs = this.idbc.select(this.tableName,this.getWhere("id",""+id));
		} catch (SQLException e) {
			throw e;
		} catch (NoSuchFieldException e) {
			throw e;
		}
		try {
			if (rs.next()) {
				try {
					this.id = rs.getInt("id");
					this.name = rs.getString("name");
					String[] c = {	rs.getString("c_blue"),rs.getString("c_pink"),
						rs.getString("c_yellow"),rs.getString("c_green"),
						rs.getString("c_brown"),rs.getString("c_orange")	};
						this.setColors(c);
				} catch (SQLException e) {
					throw e;
				}
			} else {
				throw new SQLException("Theme inconnu.","Unknown theme");
			}
		} catch (SQLException e) {
			throw e;
		} catch (NoSuchFieldException e) {
			throw e;
		}
	}
	
	/**
	 * Méthode récupérant les informations dans la BDD, par nom
	 * @param name : nom du theme
	 * @throws SQLException 
	 * @throws NoSuchFieldException : paramètre non valide
	 */
	public void read (String name) throws SQLException, NoSuchFieldException {
		ResultSet rs;
		try {
			rs = this.idbc.select(this.tableName,this.getWhere("name",name));
		} catch (SQLException e) {
			throw e;
		} catch (NoSuchFieldException e) {
			throw e;
		}
		try {
			if (rs.next()) {
				try {
					this.id = rs.getInt("id");
					this.name = rs.getString("name");
					String[] c = {	rs.getString("c_blue"),rs.getString("c_pink"),
								rs.getString("c_yellow"),rs.getString("c_green"),
								rs.getString("c_brown"),rs.getString("c_orange")	};
					this.setColors(c);
				} catch (NoSuchFieldException e) {
					throw e;
				} catch (SQLException e) {
					throw e;
				}
			} else {
				throw new SQLException("Theme inconnu.","Unknown theme");
			}
		} catch (SQLException e) {
			throw e;
		} catch (NoSuchFieldException e) {
			throw e;
		}
	}
	
	/**
	 * Méthode ajoutant le theme dans la table de themes
	 * @param name : nom du theme
	 * @throws NoSuchFieldException : paramètre non valide
	 * @throws SQLException 
	 */
	public void create(String name) throws NoSuchFieldException, SQLException {
		LinkedList<ValuedAttribute> values = new LinkedList<ValuedAttribute>();
		if (name==null || name.equals(""))
			throw new NoSuchFieldException("Nom de theme invalide.");
		try {
			values.add( new ValuedAttribute("name",name) );
		} catch (NoSuchFieldException e) {
			throw e;
		}
		try {
			this.idbc.insert(this.tableName, values);
		} catch (SQLException e) {
			throw e;
		} catch (NoSuchFieldException e) {
			throw e;
		}
		this.name = name;
		try {
			this.read(name);
		} catch (SQLException e) {
			throw e;
		} catch (NoSuchFieldException e) {
			throw e;
		}
	}
	
	/**
	 * Méthode ajoutant le theme dans la table de themes
	 * @param name : nom du theme
	 * @throws SQLException 
	 * @throws NoSuchFieldException : paramètre non valide
	 */
	public void create(String name, String[] colors) throws SQLException, NoSuchFieldException {
		LinkedList<ValuedAttribute> values = new LinkedList<ValuedAttribute>();
		if (name==null || name.equals(""))
			throw new NoSuchFieldException("Nom de theme invalide.");
		try {
			values.add( new ValuedAttribute("name",name) );
		} catch (NoSuchFieldException e) {
			throw e;
		}
		int nbColors = TPParams.COLORS.length;
		for (int i=0; i<nbColors; i++) {
			try {
				values.add( new ValuedAttribute(TPParams.COLORS[i][0],colors[i]) );
			} catch (NoSuchFieldException e) {
				throw e;
			}
		}
		try {
			this.idbc.insert(this.tableName, values);
		} catch (SQLException e) {
			throw e;
		} catch (NoSuchFieldException e) {
			throw e;
		}
		this.name = name;
		try {
			this.read(name);
		} catch (SQLException e) {
			throw e;
		} catch (NoSuchFieldException e) {
			throw e;
		}
	}
	
	/**
	 * Méthode supprimant le theme de la table de themes
	 * @throws SQLException 
	 * @throws NoSuchFieldException : paramètre non valide
	 */
	public void delete() throws SQLException, NoSuchFieldException {
		try {
			this.idbc.delete(this.tableName, this.getWhere("id",this.id));
		} catch (SQLException e) {
			throw e;
		} catch (NoSuchFieldException e) {
			throw e;
		}
	}
	
	/**
	 * Accesseur du numéro du theme
	 * @return numéro du theme
	 */
	public int getId() { return this.id; }
	/**
	 * Accesseur du nom du theme
	 * @return nom du theme
	 */
	public String getName() { return this.name; }
	/**
	 * Accesseur du nom du theme
	 * @return nom du theme
	 */
	public HashMap<String,String> getColors() { return this.colors; }
	
	/**
	 * Modifieur du numéro du theme
	 * @param id : nouveau numéro
	 * @throws SQLException 
	 * @throws NoSuchFieldException : paramètre non valide
	 */
	public void setId (int id) throws SQLException, NoSuchFieldException {
		LinkedList<ValuedAttribute> values = new LinkedList<ValuedAttribute>();
		try {
			values.add( new ValuedAttribute("id",""+id) );
		} catch (NoSuchFieldException e) {
			throw e;
		}
		try {
			this.idbc.update(this.tableName, values, this.getWhere("id",this.id));
		} catch (SQLException e) {
			throw e;
		} catch (NoSuchFieldException e) {
			throw e;
		}
		this.id=id;
	}
	
	/**
	 * Modifieur du nom du numero
	 * @param name : nouveau nom
	 * @throws SQLException 
	 * @throws NoSuchFieldException : paramètre non valide
	 */
	public void setName (String name) throws SQLException, NoSuchFieldException {
		if (name==null) throw new NoSuchFieldException("Nom vide");
		if (name.length()<TPParams.SIZES_THEME_NAME[0]) throw new NoSuchFieldException("Nom trop court");
		if (name.length()>TPParams.SIZES_THEME_NAME[1]) throw new NoSuchFieldException("Nom trop long");
		LinkedList<ValuedAttribute> values = new LinkedList<ValuedAttribute>();
		try {
			values.add( new ValuedAttribute("name",name) );
		} catch (NoSuchFieldException e) {
			throw e;
		}
		try {
			this.idbc.update(this.tableName, values, this.getWhere("id",this.id));
		} catch (SQLException e) {
			throw e;
		} catch (NoSuchFieldException e) {
			throw e;
		}
		this.name=name;
	}
	
	/**
	 * Modifieur des couleurs
	 * @param colors : nouvelles couleurs
	 * @throws NoSuchFieldException : paramètre non valide
	 * @throws SQLException
	 */
	public void setColors (String[] colors) throws NoSuchFieldException, SQLException {
		HashMap<String, String> ncolors = new HashMap<String, String>();
		if (colors==null) this.colors = new HashMap<String, String>();
		if (colors.length!=6)
			throw new NoSuchFieldException("Impossible d'associer ces catégories (incomplètes).");
		LinkedList<ValuedAttribute> values = new LinkedList<ValuedAttribute>();
		int nbColors = TPParams.COLORS.length;
		for (int i=0; i<nbColors; i++) {
			if (colors[i]==null) throw new NoSuchFieldException("Nom de catégorie vide.");
			if (colors[i].length()<TPParams.SIZES_THEME_COLOR[0]) throw new NoSuchFieldException("Nom de catégorie trop court.");
			if (colors[i].length()>TPParams.SIZES_THEME_COLOR[1]) throw new NoSuchFieldException("Nom de catégorie trop long.");
			ncolors.put(TPParams.COLORS[i][0],colors[i]);
			try {
				values.add( new ValuedAttribute("c_"+TPParams.COLORS[i][0],colors[i]) );
			} catch (NoSuchFieldException e) {
				throw e;
			}
		}
		try {
			this.idbc.update(this.tableName, values, this.getWhere("id",this.id));
		} catch (SQLException e) {
			throw e;
		} catch (NoSuchFieldException e) {
			throw e;
		}
		this.colors = ncolors;
	}
	
	/**
	 * Modifieur du nom du numero
	 * @param colors : nouvelles couleurs
	 * @throws NoSuchFieldException : paramètre non valide
	 * @throws SQLException
	 */
	public void setColor (int c, String category) throws NoSuchFieldException, SQLException {
		LinkedList<ValuedAttribute> values = new LinkedList<ValuedAttribute>();
		if (category==null) throw new NoSuchFieldException("Nom de catégorie vide.");
		if (category.length()<TPParams.SIZES_THEME_COLOR[0]) throw new NoSuchFieldException("Nom de catégorie trop court.");
		if (category.length()>TPParams.SIZES_THEME_COLOR[1]) throw new NoSuchFieldException("Nom de catégorie trop long.");
		try {
			values.add( new ValuedAttribute("c_"+TPParams.COLORS[c][0],category) );
		} catch (NoSuchFieldException e) {
			throw e;
		}
		try {
			this.idbc.update(this.tableName, values, this.getWhere("id",this.id));
		} catch (SQLException e) {
			throw e;
		} catch (NoSuchFieldException e) {
			throw e;
		}
		this.colors.put(TPParams.COLORS[c][0],category);
	}
	
	/**
	 * Méthode d'affichage de l'objet
	 */
	@Override
	public String toString () {
		String s="THEME :\n";
		s += " ID : "+this.id+"\n";
		s += " Nom : "+this.name+"\n";
		return s;
	}


	
	public static void main(String[] args) {
		try {
			Theme t;
			/*t = new Theme("genius");
			t.delete();*/
			// Création d'un theme
			t = new Theme();
			t.create("genius");
			System.out.println(t+"\n\n");
			// Lecture d'un theme
			t = new Theme("genius");
			System.out.println(t+"\n\n");
			// Suppression d'un theme
			t = new Theme();
			t.create("famille");
			// Récupération du thème créé
			int id = t.getId();
			t = new Theme(id);
			System.out.println(t+"\n\n");
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		}

	}

}
